import pandas as pd
import numpy as np
labour = pd.DataFrame([[2018, 75782, 19515, 21356, 34911],
                  [2019, 75447, 18652, 21234, 35561],
                  [2020, 75064, 17715, 21543, 35806],
                  [2021, 74652, 17072, 21712, 35868]], columns=['year', 'total_labour', 'prim_industry_employed', 'scd_industry_employed', 'tertiary_industry_employed'])
labour= labour.set_index('year',drop=True)


def gray_rel(input_df, method='mean', par_seq_index=0, rho=0.5):
    '''输入一个df,进行灰色关联分析，输出为df。其中method表示数据无量纲化方法，par_seq_index表示母序列所在的序号位置,rho为对应系数'''
    # 1.进行无量纲化
    if method == 'mean': # 均值化
        df = input_df/input_df.mean(axis=0)
    elif method == 'first': # 初值化
        df = input_df/input_df.iloc[0, :]
    elif method == 'max': # 百分比变化
        df = input_df/input_df.max()
    elif method == 'min': # 倍数变化
        df = input_df/input_df.min()

    elif method == 'min-max': # min-max变化
        df = (input_df - input_df.min()) / (input_df.max() - input_df.min())
    
    elif method == 'average_norm': # 平均归一化
        df = (input_df - input_df.mean(axis = 0)) / (input_df.max() - input_df.min())


    # 把总劳动人口那一列删除了
    x = df.drop(input_df.columns[par_seq_index], axis=1)
    # 找出第0列
    y = df.iloc[:, par_seq_index]
    # print(input_df.iloc[:, par_seq_index])
    # 2.求解系数
    abs_xik = abs(x.sub(y, axis=0))
    a = abs_xik.min().min()
    b = abs_xik.max().max()
    coef = (a + rho * b) / (abs_xik + rho * b)
    coef_m = coef.mean()
    print(coef)
    print(coef_m)
    result = pd.DataFrame(coef_m, columns=[
                          'w']).sort_values('w', ascending=False)
    return result
#调用上述函数，使用默认值
result = gray_rel(labour)
print(result)

#对医院进行综合分析
data=pd.DataFrame({
    '医院':['医院1', '医院2', '医院3', '医院4', '医院5', '医院6', '医院7', '医院8', '医院9', '医院10'],
    '门诊人数':[368107, 215654, 344914, 284220, 216042, 339841, 225785, 337457, 282917, 303455],
    '病床使用率%':[99.646, 101.961, 90.353, 80.39, 91.114, 98.766, 95.227, 88.157, 99.709, 101.392],
    '病死率%':[1.512, 1.574, 1.556, 1.739, 1.37, 1.205, 1.947, 1.848, 1.141, 1.308],
    '确诊符合率%':[99.108, 98.009, 99.226, 99.55, 99.411, 99.315, 99.397, 99.044, 98.889, 98.715],
    '平均住院日':[11.709, 11.24, 10.362, 12, 10.437, 10.929, 10.521, 11.363, 11.629, 11.328],
    '抢救成功率%':[86.657, 81.575, 79.79, 80.872, 76.024, 88.672, 87.369, 75.77, 78.589, 83.072]
})
data.set_index("医院",inplace=True)
r_n,c_n=data.shape

def min_max_deal(data,method='p',feature_range=(0, 1)):
    '''min-max归一化，data为需要进行处理的dataframe；如果method为p则为正向，为n则为逆向；设置归一化后的最小最大值'''
    y_min,y_max=feature_range
    arr=[]
    for col in data.columns:
        #进行归一化处理
        c_max=data[col].max()
        c_min=data[col].min()
        if method == 'n':
            s=(y_max-y_min)*(c_max-data[col])/(c_max-c_min)+y_min
        elif method=='p':
            s=(y_max-y_min)*(data[col]-c_min)/(c_max-c_min)+y_min
        s=s.values
        arr.append(s)
    result=np.stack(arr).T
    result=pd.DataFrame(result,columns=data.columns)
    return result
#正向指标标准化
p_cols=['门诊人数','病床使用率%','确诊符合率%','抢救成功率%']
p_df=min_max_deal(data[p_cols],'p',(0.002,1))

#负向指标标准化
n_cols=['病死率%','平均住院日']
n_df=min_max_deal(data[n_cols],'n',(0.002,1))
#进行数据合并，并将顺序与原来保持一致
normal_df=p_df.join(n_df)
# print(normal_df)
# print(data.columns)
normal_df=normal_df[data.columns]
# print(normal_df)
normal_df.index=data.index
# print(normal_df)

def gray_weight(input_df,  rho=0.5):
    '''输入一个df,进行灰色关联分析，输出为df。其中method表示数据无量纲化方法，par_seq_index表示母序列所在的序号位置,rho为对应系数'''
    x = input_df
    # 获取每行的最大值作为母序列，以此为基准
    y = input_df.max(axis=1)
    # 2.求解系数
    abs_xik = abs(x.sub(y, axis=0))
    a = abs_xik.min().min()
    b = abs_xik.max().max()
    coef = (a + rho * b) / (abs_xik + rho * b)
    coef_m = coef.mean()
    # 3.求权重
    weight=pd.DataFrame(coef_m,columns=['r'])
    # print(weight)
    #求出最后的权重
    weight['w']=weight['r']/weight['r'].sum()
    # print(weight)
    # print("权重信息",weight['w'])
    #4.计算得分
    s=np.dot(input_df.values,weight['w'].values)
    score=s*100/max(s)
    result=pd.DataFrame(score.T,columns=['score'])
    result.index=input_df.index
    result['排名']=result['score'].rank(ascending=False)
    result=result.sort_values('score',ascending=False)
    return result
 #调用函数求结果
out_df=gray_weight(normal_df)
print(out_df)